package org.code.chenwei;


import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.openjdk.jol.info.ClassLayout;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @BelongsProject: learn-learning-everyday
 * @BelongsPackage: org.chenwei
 * @Author: Chen Wei
 * @CreateTime: 2024-01-17  10:06
 * @Description: Synchronized 锁升级过程
 * @Version: 1.0
 */
@SuppressWarnings("all")
@Slf4j
public class SynchronizedLockLevel {
    //无锁  01
    @Test
    public void lock01() {
        class Lock01 {
            private String name;

            public void setName(String name) {
                this.name = name;
            }
        }
        Lock01 lock01 = new Lock01();
        String str = "123";
        lock01.setName(str);
        System.out.println(ClassLayout.parseInstance(lock01).toPrintable());
    }

    //偏向锁  同一个线程不会锁升级，哪怕多次上锁  101
    //偏向锁存在延迟四秒后启动，也就是说jvm启动四秒后创建的对象才h会开启偏向锁
    @Test
    public void lock02() throws InterruptedException {
        TimeUnit.SECONDS.sleep(5);
        class Lock01 {
            String name;
        }
        Lock01 lock01 = new Lock01();

        synchronized (lock01) {
            System.out.println(ClassLayout.parseInstance(lock01).toPrintable());
        }
    }


    //轻量级锁  00
    //不同线程串行锁竞争，锁会升级为轻量级锁，不存在并发状况
    @Test
    public void lock03() throws InterruptedException {
        TimeUnit.SECONDS.sleep(5);
        class Lock01 {
            String name;
        }
        Lock01 lock01 = new Lock01();

/*        Thread thread01 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock01) {
                    System.out.println(ClassLayout.parseInstance(lock01).toPrintable());
                }
            }
        });*/
        synchronized (lock01) {
            System.out.println(ClassLayout.parseInstance(lock01).toPrintable());
        }
        Thread thread02 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock01) {
                    System.out.println(ClassLayout.parseInstance(lock01).toPrintable());
                }
            }
        });
//        thread01.start();
        thread02.start();

//        thread01.join();
        thread02.join();
    }

    //重量级锁  10 并发状况会升级为重量级锁也就是互斥锁
    @Test
    public void lock04() throws InterruptedException {

        class Lock01 {
            String name;
        }
        Lock01 lock01 = new Lock01();

        Thread thread01 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock01) {
                    System.out.println(ClassLayout.parseInstance(lock01).toPrintable());
                    try {
                        TimeUnit.SECONDS.sleep(2);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        Thread thread02 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock01) {
                    System.out.println(ClassLayout.parseInstance(lock01).toPrintable());
                    try {
                        TimeUnit.SECONDS.sleep(2);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        thread01.start();
        thread02.start();

        thread01.join();
        thread02.join();
    }

    private static final Object lockObj = new Object();
    private ReentrantLock reentrantLock=new ReentrantLock(true);
    private ReentrantReadWriteLock.ReadLock readLock=new ReentrantReadWriteLock().readLock();
    private ReentrantReadWriteLock.WriteLock writeLock=new ReentrantReadWriteLock().writeLock();
    //可重入锁   也属于偏向锁
    @Test
    public void reLock05() throws InterruptedException {
        Thread thread = new Thread(() -> {
            relock();
        });
        thread.start();
        thread.join();
    }

    private static Integer i = 0;

    public void relock() {
        synchronized (lockObj) {
            System.out.println(ClassLayout.parseInstance(lockObj).toPrintable());
            if (i == 3) {
                return;
            } else {
                i++;
                log.info("i={}", i);
                relock();
            }
        }
    }
}
